import os

doc_src_path = os.path.dirname(__file__)
janim_path = os.path.abspath(os.path.join(doc_src_path, '../../janim'))

generate_autodoc_exclude = ['janim.constants', 'janim.logger', 'janim.typing',
                            'janim.cli', 'janim.examples', 'janim.locale']
force_generate_autodoc = False

exclude_substrings = ['._', 'ui_']

extra_include = {
    'janim': ['constants']
}


def generate_autodoc(local_path: str, module_path: str) -> bool:
    if module_path in generate_autodoc_exclude:
        return False

    search_path = os.path.join(janim_path, local_path)
    rst_path = os.path.join(doc_src_path, 'janim', local_path)
    lst = os.listdir(search_path)

    generated_dirs = []
    generated_files = []

    for filename in lst:
        skip = False
        for substr in exclude_substrings:
            if substr in filename:
                skip = True
                break
        if skip:
            continue
        sub_path = os.path.join(search_path, filename)

        if os.path.isdir(sub_path):
            if generate_autodoc(os.path.join(local_path, filename), f'{module_path}.{filename}'):
                generated_dirs.append(filename)

        elif os.path.isfile(sub_path):
            name = _generate_autodoc_file(module_path, filename, rst_path)
            if name is not None:
                generated_files.append(name)

        else:
            raise Exception(f'{sub_path} is not available')

    if generated_dirs or generated_files:
        with open(os.path.join(rst_path, 'modules.rst'), 'w') as f_modules:
            try:
                name = module_path[module_path.rindex('.') + 1:]
            except ValueError:
                name = module_path

            f_modules.write(
                f'{name}\n'
                f'{"=" * len(name)}\n'
                '\n'
                '.. Do not modify this file, this file is generated by autodoc.py and your changes will lost.\n'
                '\n'
                '.. toctree::\n'
                '   :maxdepth: 1\n\n'
            )

            for dir in generated_dirs:
                f_modules.write(f'   {dir}/modules.rst\n')

            extras = extra_include.get(module_path, None)
            if extras is not None:
                for extra in extras:
                    f_modules.write(f'   {extra}\n')

            for file in generated_files:
                f_modules.write(f'   {file}\n')

        return True

    return False


def _generate_autodoc_file(module_path: str, filename: str, rst_path: str) -> str | None:
    if not filename.endswith('.py') or filename.startswith('__'):
        return None

    name = filename[:-3]
    module_name = f'{module_path}.{name}'
    if module_name in generate_autodoc_exclude:
        return None

    rst_file_path = os.path.join(rst_path, f'{name}.rst')
    os.makedirs(rst_path, exist_ok=True)

    if not force_generate_autodoc and os.path.exists(rst_file_path):
        print('Exists:\t', module_name)
    else:
        with open(rst_file_path, 'w') as f:
            f.write(
                f'{name}\n'
                f'{"=" * len(name)}\n'
                '\n'
                f'.. automodule:: {module_name}\n'
                '   :members:\n'
                '   :undoc-members:\n'
                '   :show-inheritance:\n\n'
            )
        print('Generated:\t', module_name)

    return name


generate_autodoc('', 'janim')
